<?php

class Core_Data_Generator {

    private $DefinedStructure;
    private $strHTMLReport = "";

    function __construct () {
        $this->DefinedStructure = new Core_Data_UDD_Structure ();
    }

    /**
     * Outputs an HTML document with a report.
     *
     * The report details everything the generator has done so far.
     * 
     * @param string $strHTML
     */
    public function report ( &$strHTML = null ) {

        $objHTML = new Core_Presentation_HTML_Document ();
        $objHTML->Title = "Core_Data_Generator::report()";

        $objHTML->addStyle( "*", "color", "white" );
        $objHTML->addStyle( "*", "font-family", '"Helvetica", "Verdana"' );
        $objHTML->addStyle( "body", "background-color", "black" );
        $objHTML->addStyle( "p", "font-family", '"Courier", "Courier New"' );
        $objHTML->addStyle( "p", "font-weight", "bold" );
        $objHTML->addStyle( "p", "font-size", "10pt" );

        $objHTML->importHTML( "<h1>Core_Data_SQL_Generator::report()</h1>" );
        $objHTML->importHTML( $this->strHTMLReport );

        if ( isset( $strHTML ) ) {
            $strHTML = $objHTML->getHTML();
        } else {
            echo $objHTML->getHTML();
        }

    }

    public function addDefinition ( $strFilename ) {
        $this->DefinedStructure->interpretDocument( $strFilename );
    }

    public function generateModels () {

    }

    /**
     * Generates databases as defined.
     *
     * @param Core_Data_SQL_Connection $Connection
     * @param boolean $boolWipe
     * @exception UnexpectedValueException 0 No databases seems to be defined.
     */
    public function generateDatabases ( Core_Data_SQL_Connection $Connection, $boolWipe = false ) {

        $this->strHTMLReport .= "<h2>Core_Data_SQL_Generator::generateDatabases()</h2>";

        // Check if any databases has been defined and throw an exception if not.
        if ( count( (array) $this->DefinedStructure->databases() ) == 0 ) {
            throw new UnexpectedValueException( "No databases seems to be defined.", 0);
        }

        $boolWipe = true;

        $objActualStructure = new Core_Data_SQL_Structure();

        foreach ( $this->DefinedStructure->databases() as $objDefinedDatabase ) {

            // NOTE: This all assumes that the databases we intend to use are already there.

            if ( (string) $objDefinedDatabase == "__default" ) {
                $objActualStructure->addDatabase( $Connection );
            } else {
                $objActualStructure->addDatabase( $Connection, (string) $objDefinedDatabase );
            }

            $strCurrentDatabase = $Connection->getCurrentDatabase();
            $objActualDatabase = $objActualStructure->databases()->$strCurrentDatabase;

            // Wipe the database if $boolWipe is true.
            if ( $boolWipe ) {
                $objActualDatabase->wipe();
                $this->strHTMLReport .= "<p>The database `" . $objActualDatabase . "` has been wiped.</p>";
            }

            // Walk through the defined tables and create them.
            foreach ( $objDefinedDatabase->tables() as $objDefinedTable ) {

                $strQuery = "CREATE TABLE `" . $objDefinedTable . "` ( ";

                $i = 1;
                foreach ( $objDefinedTable->fields() as $objDefinedField ) {

                    $strQuery .= "`" . $objDefinedField . "` ";
                    $strQuery .= $this->getQueryTextFromUDDDataType( $objDefinedField->getDataType(), $objDefinedField->getSize() ) . " ";
                    $strQuery .= ( $objDefinedField->isRequired() ) ? "NOT NULL" : "NULL";
                    if ( $objDefinedField->getKeyType() == Core_Data_UDD_KeyTypes::UNIQUE ) {
                        $strQuery .= " AUTO_INCREMENT PRIMARY KEY";
                    }

                    if ( $i++ < count( (array) $objDefinedTable->fields() ) ) {
                        $strQuery .= ", ";
                    }

                }

                $strQuery .= " )";

                $Connection->query( $strQuery );

                $this->strHTMLReport .= "<p>The table `" . $objDefinedTable . "`, along with " . count( (array) $objDefinedTable->fields() ) . " fields, has been created.</p>";

            }

        }

    }

    /**
     * Converts an UDD data type to SQL text.
     *
     * @param const $constDataType
     * @return string
     */
    private function getQueryTextFromUDDDataType ( $constDataType, $intSize ) {

        // Q: Are these data types specific for MySQL?
        // TODO: Ensure that it works for all supported server types.

        switch ( $constDataType ) {

            case Core_Data_UDD_DataTypes::INT8:
                return "TINYINT";

            case Core_Data_UDD_DataTypes::INT16:
                return "SMALLINT";

            case Core_Data_UDD_DataTypes::INT24:
                return "MEDIUMINT";

            case Core_Data_UDD_DataTypes::INT32:
                return "INT";

            case Core_Data_UDD_DataTypes::INT64:
                return "BIGINT";

            case Core_Data_UDD_DataTypes::TEXT:
                if ( $intSize ) {
                    return "VARCHAR(" . $intSize . ")";
                } else {
                    return "TEXT";
                }

            case Core_Data_UDD_DataTypes::EMAIL:
                return "VARCHAR(255)";

            case Core_Data_UDD_DataTypes::MD5:
                return "CHAR(32)";

            case Core_Data_UDD_DataTypes::BOOLEAN:
                return "TINYINT(1)";

            case Core_Data_UDD_DataTypes::UNIXTIME32:
                return "INT";

            case Core_Data_UDD_DataTypes::UNIXTIME64:
                return "BIGINT";

        }

    }

}

?>
